// author: shelman
// description：封装了消息队列（Message Queue）的接口
#ifndef msgqueue_util_h
#define msgqueue_util_h


#include <stdio.h>
#include <stdlib.h>
#include <string.h>


#ifdef __cplusplus
extern "C"
{
#endif

#if defined(WIN32) || defined(WIN64) || defined(_WIN32) || defined(_WIN64)
#define MSGQUEUEUTIL_DLL_EXPORT __declspec(dllexport)
#else
#define MSGQUEUEUTIL_DLL_EXPORT __attribute__((visibility("default")))
#endif

// 消息队列最大支持32个，支持消息队列的创建、销毁、打开、关闭，数据读写，数据格式自行定义和字节流。
// 也可支持设置数据回调接口，然后loop_start，自行数据回调，停止时调用loop_stop。
// 在Linux系统中，消息队列的默认传输数据最大值由内核参数msgmax决定，默认值通常是8192字节，可进行修改。

/******************************************************************
 * 功能：创建并打开消息队列，注：多进程通信时，消息队列需遵循谁创建谁销毁的原则
 * 输入参数：
 *      key：通信双方约定的相同键值
 * 返回值：
 *      int：消息队列的fd信息，小于0 -- 失败，大于等于0 -- 成功
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT int msgqueue_create_and_open_by_key(int key);

/******************************************************************
 * 功能：创建并打开消息队列，注：多进程通信时，消息队列需遵循谁创建谁销毁的原则
 * 输入参数：
 *      mq_path：通信双方约定的相同路径信息，路径未存在时主动创建，销毁队列时删除路径
 *              注：路径需要有读写访问权限
 *      mq_proj_id：通信双方约定的key信息，通常为一个int32的数
 * 返回值：
 *      int：消息队列的fd信息，小于0 -- 失败，大于等于0 -- 成功
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT int msgqueue_create_and_open(const char* mq_path, int mq_proj_id);

/******************************************************************
 * 功能：打开一个已经存在的消息队列；
 *      一般情况下进程A、B通信时，可以由A创建并打开，B使用时只打开即可
 * 输入参数：
 *      key：通信双方约定的相同键值
 * 返回值：
 *      int：消息队列的fd信息，小于0 -- 失败，大于等于0 -- 成功
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT int msgqueue_open_by_key(int key);

/******************************************************************
 * 功能：打开一个已经存在的消息队列；
 *      一般情况下进程A、B通信时，可以由A创建并打开，B使用时只打开即可
 * 输入参数：
 *      mq_path：通信双方约定的相同路径信息，前提是路径先要被创建
 *      mq_proj_id：通信双方约定的key信息，通常为一个int32的数
 * 返回值：
 *      int：消息队列的fd信息，小于0 -- 失败，大于等于0 -- 成功
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT int msgqueue_open(const char* mq_path, int mq_proj_id);

/******************************************************************
 * 功能：关闭一个已经存在的消息队列，注：这里主要是设置消息队列的无效标识
 * 输入参数：
 *      fd：消息队列的fd
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT void msgqueue_close(int fd);

/******************************************************************
 * 功能：关闭并销毁消息队列，注：多进程通信时，消息队列需遵循谁创建谁销毁的原则
 * 输入参数：
 *      fd：消息队列的fd
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT void msgqueue_close_and_destroy(int fd);

/******************************************************************
 * 功能：从消息队列中读取数据
 * 输入参数：
 *      fd：消息队列的fd
 *      buffer：读取数据的缓存空间
 *      buf_size：数据缓存空间的大小
 * 返回值：
 *      int：读取结果，大于0 -- 成功，具体读取数据的大小，-1 -- 不成功
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT int msgqueue_read(int fd, void* buffer, size_t buf_size);

/******************************************************************
 * 功能：把数据写入消息队列中
 * 输入参数：
 *      fd：消息队列的fd
 *      buffer：待写入数据的缓存空间
 *      size：数据大小
 * 返回值：
 *      int：写入结果，0 -- 成功，非0 -- 不成功
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT int msgqueue_write(int fd, void* buffer, size_t size);

/*********************以下为通过回调模式自行读取数据的方式********************************/
/******************************************************************
 * 功能：消息队列处理回调函数类型
 * 输出参数：
 *      fd：消息队列的fd
 *      buffer：读取的数据存放缓存空间
 *      size：读取数据的大小
 *      context：调用的上下文实例
 * ****************************************************************/
typedef void (*pfn_mq_readdata_callback)(int fd, void* buffer, size_t size, void *context);

/******************************************************************
 * 功能：设置消息队列处理回调函数
 * 输出参数：
 *      pfn：回调函数
 *      context：调用的上下文实例
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT void msgqueue_set_readdata_callback(pfn_mq_readdata_callback pfn, void *context);

/******************************************************************
 * 功能：开始消息队列自动读取数据的线程
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT void msgqueue_loop_start();

/******************************************************************
 * 功能：停止消息队列自动读取数据的线程
 * ****************************************************************/
MSGQUEUEUTIL_DLL_EXPORT void msgqueue_loop_stop();


#ifdef __cplusplus
} // extern "C"
#endif

#endif // msgqueue_util_h
